// Copyright (C) Kumo inc. and its affiliates.
// Author: Jeff.li lijippy@163.com
// All rights reserved.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published
// by the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see <https://www.gnu.org/licenses/>.
//


#include <pollux/dwio/common/bit_concatenation.h>

namespace kumo::pollux::dwio::common {
    void BitConcatenation::append(
        const uint64_t *bits,
        int32_t begin,
        int32_t end) {
        int32_t numBits = end - begin;
        if (!bits || bits::isAllSet(bits, begin, end, true)) {
            appendOnes(numBits);
            return;
        }
        if (!hasZeros_) {
            bits::fillBits(ensureSpace(numBits), 0, numBits_, true);
            hasZeros_ = true;
        }
        bits::copyBits(bits, begin, ensureSpace(numBits), numBits_, numBits);
        numBits_ += numBits;
        setSize();
    }

    void BitConcatenation::appendOnes(int32_t numOnes) {
        if (hasZeros_) {
            bits::fillBits(ensureSpace(numOnes), numBits_, numBits_ + numOnes, 1);
        }
        numBits_ += numOnes;
        if (hasZeros_) {
            setSize();
        }
    }

    uint64_t *BitConcatenation::ensureSpace(int32_t numBits) {
        if (!*buffer_) {
            *buffer_ = AlignedBuffer::allocate<bool>(numBits_ + numBits, &pool_, true);
        } else if (numBits_ + numBits > (*buffer_)->capacity() * 8) {
            AlignedBuffer::reallocate<bool>(buffer_, 2 * (numBits_ + numBits));
        }
        return (*buffer_)->asMutable<uint64_t>();
    }
} // namespace kumo::pollux::dwio::common
